Baby-Step, Giant-Step
Baby-Step, Giant-Step is an algorithm for computing the discrete logarithm in a given group.
The problem statement, that we are trying to solve, is the following. Given
Which is to say, we are evaluating
Motivation, and Description of Method
Naively, one might consider calculating powers of the primitive root
If we happen to find
Consider all consecutive powers of the primitive root listed in order as in the diagram below:

These are organised into sets of size
Set
We now take the giant steps. Consider that

Once it is, we know at that point that
Solve
First note that in this case our group is of order
Since we did not find
using the extended euclidean algorithm, where
This results in
We then have
Since we know that
Implementation
Here is an implementation of the algorithm in the specific case where the underlying group is the group of units modulo
fn main() {
println!("{}", baby_step_giant_step(13, 2, 3));
}
fn modular_exponent(base : u64, power : u64, modulus : u64) -> u64 {
let mut result = 1;
for _ in 0..power {
result *= base % modulus;
}
result % modulus
}
/// We must have that:
/// - `modulus` is `prime`
/// - primitive_root is actually a primitive_root modulo `modulus`
/// - `logarithm` is some positive integer
/// This then computers `power` such that:
/// `primitive_root`^`power` = `logarithm` (mod `modulus`)
fn baby_step_giant_step(modulus : u64, primitive_root : u64, logarithm : u64) -> u64 {
// Since modulus is prime, phi(modulus) = modulus - 1
let group_order = modulus - 1;
let m = (group_order as f64).sqrt() as u64 + 1;
// Compute initial powers of the primitive_root (up to floor(sqrt(group_order)))
let powers = {
let mut powers = std::collections::HashMap::with_capacity(m as usize);
let mut power = 1;
for j in 0..m {
powers.insert(power, j);
power *= primitive_root % modulus;
}
powers
};
let mut guess = logarithm % modulus;
for i in 0..m {
match powers.get(&guess) {
Some(power) => {
return i * m + power;
},
None => {
guess = (guess * modular_exponent(primitive_root, group_order - m, modulus)) % modulus;
},
}
}
unreachable!()
}